package cn.yeziji.forum.dao.impl;

import cn.yeziji.forum.dao.base.ForumAnswerBaseDao;
import cn.yeziji.forum.dao.intf.ForumAnswerDao;
import cn.yeziji.forum.dao.iquery.AnswerQuery;
import cn.yeziji.forum.dao.iquery.QuestionAnswerQuery;
import cn.yeziji.forum.dto.answer.AnswerDTO;
import cn.yeziji.forum.entity.ForumAnswerEntity;
import cn.yeziji.forum.entity.ForumQuestionAnswerEntity;
import cn.yeziji.forum.mapper.ForumQuestionAnswerMapper;
import cn.yeziji.forum.service.NoticeService;
import cn.yeziji.forum.utils.JwtOperaUtils;
import cn.yeziji.forum.vo.answer.AnswerVO;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 回复问题业务实现层
 *
 * @author gzkemays
 * @since 2022/11/14 3:50 PM
 */
@Repository
public class ForumAnswerDaoImpl extends ForumAnswerBaseDao
    implements ForumAnswerDao, NoticeService {
  @Resource ForumQuestionAnswerMapper questionAnswerMapper;
  @Resource HttpServletRequest request;

  @Override
  public List<AnswerVO> list(Integer id) {
    Integer userId = JwtOperaUtils.getUserIdIfZero(request);
    List<Map<String, Object>> maps =
        mapper.listMaps(AnswerQuery.getAnswerByQuestionIdQuery(id, userId));
    if (!maps.isEmpty()) {
      Map<Integer, AnswerVO> parentMap = new TreeMap<>();
      for (Map<String, Object> map : maps) {
        // 评论必然是先有父后有子
        AnswerVO answerVO = new AnswerVO(map);
        if (map.containsKey("parentAnswerId")) {
          // 子级
          Integer parentAnswerId = (Integer) map.get("parentAnswerId");
          if (parentMap.containsKey(parentAnswerId)) {
            // 如果它的子级评论的父级是顶级回复
            AnswerVO parentVO = parentMap.get(parentAnswerId);
            List<AnswerVO> child = parentVO.getChild();
            if (child == null) child = new ArrayList<>();
            // 赋值 nickname
            answerVO.setAtNickname(parentVO.getNickname());
            child.add(answerVO);
            parentVO.setChild(child);
            parentMap.put(parentAnswerId, parentVO);
          } else {
            // 如果子级评论是父级的子级
            parent:
            for (Map.Entry<Integer, AnswerVO> entry : parentMap.entrySet()) {
              AnswerVO parentVO = entry.getValue();
              List<AnswerVO> child = parentVO.getChild();
              // 查看父级里的子级是否为父级
              for (AnswerVO vo : child) {
                if (vo.getId().equals(parentAnswerId)) {
                  // 查找到塞入后退出
                  answerVO.setAtNickname(vo.getNickname());
                  child.add(answerVO);
                  parentVO.setChild(child);
                  parentMap.put(parentVO.getId(), parentVO);
                  break parent;
                }
              }
            }
          }
        } else {
          // 父级
          parentMap.put(answerVO.getId(), answerVO);
        }
      }
      return new ArrayList<>(parentMap.values());
    }
    return null;
  }

  @Override
  @Transactional(rollbackFor = {RuntimeException.class})
  public void replay(AnswerDTO dto) {
    Integer mode = dto.getMode();
    // 判断实体类型
    ForumAnswerEntity entity =
        Objects.equals(mode, QUESTION_MODE) ? dto.answerEntity() : dto.replayEntity();
    Integer userId = JwtOperaUtils.getUserIdByRequest(request);
    entity.setUserId(userId);
    Integer dtoId = dto.getId();
    if (Objects.equals(mode, QUESTION_MODE)) {
      // 回答问题
      save(entity);
      Integer answerId = entity.getId();
      questionAnswerMapper.save(new ForumQuestionAnswerEntity(dtoId, answerId));
    } else if (Objects.equals(mode, ANSWER_MODE)) {
      // 回复
      entity.setParentAnswerId(dtoId);
      save(entity);
      // 查找父级的问题并追加
      ForumQuestionAnswerEntity one =
          questionAnswerMapper.findOne(QuestionAnswerQuery.findOneByAnswerId(dtoId));
      questionAnswerMapper.save(new ForumQuestionAnswerEntity(one.getQuestionId(), entity.getId()));
    }
  }

  @Override
  public List<ForumAnswerEntity> getUser7DaysAnswer(Integer userId) {
    return mapper.listEntity(AnswerQuery.getUser7DaysAnswerQuery(userId));
  }

  @Override
  public void notice(Object data) {}
}
